package br.edu.ufcg.fpc;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import br.edu.ufcg.fpc.util.Util;

/**
 * Classe abstrata que possui o metodo tido como regiao critica.
 */
public abstract class CriticalRegion extends Thread {

	protected static final int ITERATIONS = 1024;
	static final File FILE = new File("increment.txt");
	
	private List<Double> times = new LinkedList<>();
	
	/**
	 * Regiao critica.
	 */
	protected void increment() {
		String content = Util.readFromFile(FILE);
		if (content == null || content.trim().isEmpty()) {
			content = String.format("Thread %d: %d", Thread.currentThread().getId(), 1);
		} else {
			String[] auxList = content.split("\n");
			int length = auxList.length;
			String lastLine = auxList[length-1];
			long newValue = Long.parseLong(lastLine.split(":")[1].trim())+1;
			content += String.format("\nThread %d: %d", Thread.currentThread().getId(), newValue);
		}
		Util.writeToFile(FILE, content);
	}
	
	/**
	 * Metodo abstrato. Cada classe filha deve implementar esse metodo 
	 * utilizando a determinada trava e invocando o metodo increment().
	 */
	protected abstract void executeCriticalRegion();

	@Override
	public void run() {
		int i = 0;
		while (i < ITERATIONS / MutualExclusion.nThreads) {
			executeCriticalRegion();
			i++;
		}
	}

	protected void addTime(Long t) {
		times.add((double)t);
	}
	
	public List<Double> getTimes() {
		return new ArrayList<>(times);
	}

}
